#ifndef ___fuse_readdir
#define ___fuse_readdir 1

#ifndef FUSE_USE_VERSION
#define FUSE_USE_VERSION 28
#endif

#include <stdio.h>
#include <stdlib.h>
#include "mtlib.c"
#include <fuse.h>
#include <fcntl.h>
#include <errno.h>
#include "logging.c"

struct datosLeerDir {
	char * path;
	void * buffer;
	long pos;
	char estado;
	fuse_fill_dir_t retFiller;
};

//PROTOTIPOS
int fuse_readdir(const char *, void *,fuse_fill_dir_t, off_t,struct fuse_file_info *);
void ___fuse_procesar_mensaje_readdir(unsigned char centro_readdir, mti_mensaje, struct datosLeerDir *);

//LEER DIRECTORIO
int fuse_readdir(const char * path, void * buffer,fuse_fill_dir_t filler, off_t offset, struct fuse_file_info * ptr) {

   int resultado;
   mti_mensaje datosMensaje;
   unsigned char centro_readdir = 0;
   unsigned int descriptorConexion;
   struct datosLeerDir datos;

   	   datos.pos = offset;
   	   datos.path = path;
   	   datos.estado = 0;
   	   datos.buffer = buffer;
   	   datos.retFiller = filler;

   	   while (centro_readdir == 0)
   		  centro_readdir = mtf_obtener_descriptor(1024);

   	   descriptorConexion = mtf_conectar(centro_readdir, MTP_INTERNO, centro_fat);

   	   if (descriptorConexion == 0) {
   		   mtf_liberar_descriptor(centro_readdir);
   		   return -EAGAIN;
   	   }

   	   resultado = mtf_enviar_mensaje(centro_readdir, descriptorConexion, MTE_OBTENER_DATOS_DIR, (char *) datos.path); //le envio un mensaje
   	   //al centro del sistema fat que le va a solicitar al disco los sectores necesarios para saber el contenido del
   	   //directorio

   	   if (resultado == 0) {
   		  mtf_desconectar(centro_readdir, descriptorConexion);
   		  mtf_liberar_descriptor(centro_readdir);
   		  return -EAGAIN;
   	   }

   	   while (!datos.estado) {

   		  if (!mtf_recibir_mensajes(centro_readdir)) continue;

   		  datosMensaje = mtf_siguiente_mensaje(centro_readdir);
   		  ___fuse_procesar_mensaje_readdir(centro_readdir, datosMensaje, &datos);
   		  mtf_descartar_mensaje(centro_readdir, datosMensaje.codigo);

   	   }

   	   mtf_desconectar(centro_readdir, descriptorConexion); //desconecto la conexion del centro de mensajes
   	   mtf_liberar_descriptor(centro_readdir); //libero centro de mensajes con sus datos y conexiones

   	   switch (datos.estado) {

   	    case 1:
   	    	return -ENOENT;//el path esta vacio
   	    case 2:
   	    	return -ENOTDIR; //no es un directorio
   	    default:
   	    	return EXIT_SUCCESS;
   	  }
}

void ___fuse_procesar_mensaje_readdir(unsigned char centro_readdir, mti_mensaje datosMensaje, struct datosLeerDir * datosDir) {

	if (datosMensaje.categoria != MTA_MENSAJE) return;

	  switch (datosMensaje.tipo) {

	    case MTE_NULL:

	      mtf_enviar_mensaje(centro_readdir, datosMensaje.remitente, MTR_NULL);

	    break;

	    case MTR_NULL: case MTQ_MENSAJE_NO_VALIDO:

	    break;

	    //MENSAJES PARA LEER UN DIRECTORIO
	    case MTR_SIGUIENTE_ARCHIVO:
	     {
	      //declaro variables,, que utiliza el mensaje recibido como parametros
	      char * nombreArchivo = NULL;
	      char * nombreDirectorio = NULL;
	      fuse_fill_dir_t filler; //filler es una funcion que inserta entradas de directorio en una estructura

	      //obtengo datos del mensaje
	      	  mtf_obtener_datos(centro_readdir, datosMensaje.codigo,(char **) &nombreDirectorio,
	      			  	  	  	  (char **) &nombreArchivo);

	      	  (datosDir -> retFiller) (datosDir -> buffer, nombreArchivo, NULL, 0); //retorno el nombre del archivo o directorio obtenido,, al kernel
	      	  // para mostrar por pantalla
	      	  (datosDir -> retFiller) (datosDir -> buffer, nombreDirectorio, NULL, 0); //idem arriba

	      	  log_registrar(descArch, "FUSE", LOG_INFO, "DirectorioLeido ArchivoLeido %s %s \n", nombreArchivo, nombreDirectorio);

	      	  free(nombreArchivo);
	      	  free(nombreDirectorio);
	      }
	     break;

	     case MTR_FIN_DIRECTORIO:
	     {
	      	char * nombreDirectorio = NULL;

	      		mtf_obtener_datos(centro_readdir, datosMensaje.codigo,(char **) &nombreDirectorio);

	      			(datosDir -> retFiller) (datosDir -> buffer,".",NULL,0); //agrego entradas de directorio
	      			(datosDir -> retFiller) (datosDir -> buffer,"..",NULL,0); //idem arriba
	      		
	      		free(nombreDirectorio);
	      		datosDir -> estado = 255;

	     }
	     break;

	     case MTR_NO_LEYO_DIRECTORIO:
	     {
	      	char * nombreDirectorio = NULL;
	      	char motivo;

	      		mtf_obtener_datos(centro_readdir, datosMensaje.codigo,(char **) &nombreDirectorio, (char *)
	      							&motivo);

	      		log_registrar(descArch, "FUSE", LOG_WARN, "No leyo directorio %s \n", nombreDirectorio);
	      		free(nombreDirectorio);
	      		datosDir -> estado = motivo;

	     break;
	     }

	     default:

	           mtf_enviar_mensaje(centro_readdir, datosMensaje.remitente, MTQ_MENSAJE_NO_VALIDO);

	     break;
	  }
}

#endif
